﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;

namespace osuStd2Key
{
    public class osuNote
    {
        public enum NoteType
        {
            None,
            Circle,
            Slide,
            Spinner
        }
        public class Note
        {
            public int x;
            public int y;
            public int TimeMs;
            public int NoteType;
            public int SoundType;
            public string ExtraInfo; // ???
            public bool isCircle
            {
                get { return (NoteType & 0x1) == 0x1; }
            }
            public bool isSlide
            {
                get { return (NoteType & 0x2) == 0x2; }
            }
            public bool isNewCombo
            {
                get { return (NoteType & 0x4) == 0x4; }
            }
            public bool isSpinner
            {
                get { return (NoteType & 0x8) == 0x8; }
            }
            public bool isSoundNormal
            {
                get { return (SoundType == 0 ); }
            }
            public bool isSoundWhistle {
                get { return (SoundType & 0x2) == 0x2; }
            }
            public bool isSoundFinish
            {
                get { return (SoundType & 0x4) == 0x4; }
            }
            public bool isSoundClap
            {
                get { return (SoundType & 0x8) == 0x8; }
            }
            public NoteType RealNoteType
            {
                get
                {
                    if (isCircle) return osuNote.NoteType.Circle;
                    if (isSlide) return osuNote.NoteType.Slide;
                    if (isSpinner) return osuNote.NoteType.Spinner;
                    return osuNote.NoteType.None;
                }
            }
            public Note(string line)
            {
                string[] info = line.Split(new char[] { ',' }, 6);
                x = int.Parse(info[0]);
                y = int.Parse(info[1]);
                TimeMs = int.Parse(info[2]);
                NoteType = int.Parse(info[3]);
                SoundType = int.Parse(info[4]);
                ExtraInfo = info.Length>=6 ? info[5] : "";
            }
        }
        public List<Note> Notes = new List<Note>();
        protected string rawString;
        public string Artist = "";
        public string Version = "";

        public osuNote() { }
        public osuNote(string content)
        {
            rawString = content;
            var lines = getRawSection("HitObjects");
            foreach (string line in lines)
            {
                if (string.IsNullOrEmpty(line.Trim())) continue;
                Notes.Add(new Note(line.Trim()));
            }
            var infoLines = getRawSection("Metadata");
            foreach (string infoLine in infoLines)
            {
                if (infoLine.Trim() == "") continue;
                string[] info = infoLine.Split(new char[] { ':' }, 2);
                if (info.Length == 1) continue;
                if (info[0] == "Artist") Artist = info[1];
                //else if (info[0] == "ArtistUnicode") Artist = UnicodeToString(info[1]);
                else if (info[0] == "Version") Version = info[1];
            }
        }
        public static string UnicodeToString(string srcText)
        {
            string dst = "";
            string src = srcText;
            int len = srcText.Length / 6;
            for (int i = 0; i <= len - 1; i++)
            {
                string str = "";
                str = src.Substring(0, 6).Substring(2);
                src = src.Substring(6);
                byte[] bytes = new byte[2];
                bytes[1] = byte.Parse(int.Parse(str.Substring(0, 2), NumberStyles.HexNumber).ToString());
                bytes[0] = byte.Parse(int.Parse(str.Substring(2, 2), NumberStyles.HexNumber).ToString());
                dst += Encoding.Unicode.GetString(bytes);
            }
            return dst;
        }
        public double getBPM() {
            string[] splitedStr = getRawSection("TimingPoints")[0].Trim().Split(new char[] { ',' });
            return double.Parse(splitedStr[1]);
        }

        public List<string> getRawSection(string sectionName)
        {
            string[] lines = rawString.Split(new string[] { "\r\n" }, StringSplitOptions.None);
            string sectionHeader = string.Format("[{0}]", sectionName);
            List<string> content = new List<string>();
            bool inSection = false;
            for(int i=0; i < lines.Length; i++)
            {
                if (!inSection)
                {
                    if (lines[i].Trim() == sectionHeader)
                        inSection = true;
                    continue;
                }
                if (inSection && lines[i].Trim().StartsWith("[")) break;
                content.Add(lines[i]);
            }
            return content;
        }
    }
}
